package com.canaan.business.service.inOutStock.impl;


import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import com.canaan.business.common.enums.basic.ContainerStatusEnum;
import com.canaan.business.common.enums.basic.WhetherEnum;
import com.canaan.business.common.enums.inOutStock.*;
import com.canaan.business.common.enums.invoice.MaterialPreparationStatusEnum;
import com.canaan.business.common.enums.invoice.SaleOrderEnum;
import com.canaan.business.common.enums.quality.QualityResultEnum;
import com.canaan.business.common.enums.quality.QualityTaskStatusEnum;
import com.canaan.business.common.enums.quality.QualityTypeEnum;
import com.canaan.business.common.enums.storehouse.BarcodeRecordStatusEnum;
import com.canaan.business.common.enums.storehouse.InOutStorageOperationEnum;
import com.canaan.business.domain.basic.*;
import com.canaan.business.domain.bill.*;
import com.canaan.business.domain.inOutStock.*;
import com.canaan.business.domain.invoice.WmsSalesOrder;
import com.canaan.business.domain.quality.ProductQualityMainTask;
import com.canaan.business.domain.storehouse.WmsBarcodeRecord;
import com.canaan.business.domain.storehouse.WmsInOutStorage;
import com.canaan.business.domain.storehouse.WmsStorehouseStock;
import com.canaan.business.domain.vo.PickerTaskOrderVo;
import com.canaan.business.domain.vo.YardageGoodsTaskOrderConfirmVo;
import com.canaan.business.mapper.inOutStock.PickerTaskOrderMapper;
import com.canaan.business.service.basic.*;
import com.canaan.business.service.bill.IAdjustOutBillService;
import com.canaan.business.service.bill.IMaterialPreparationService;
import com.canaan.business.service.bill.IPickProductBillService;
import com.canaan.business.service.bill.IPurchaseReturnBillService;
import com.canaan.business.service.inOutStock.*;
import com.canaan.business.service.invoice.IWmsSalesOrderService;
import com.canaan.business.service.quality.IProductQualityItemService;
import com.canaan.business.service.quality.IProductQualityMainTaskService;
import com.canaan.business.service.storehouse.IWmsBarcodeRecordService;
import com.canaan.business.service.storehouse.IWmsInOutStorageService;
import com.canaan.business.service.storehouse.IWmsStorehouseStockService;
import com.canaan.common.constant.PrefixConstants;
import com.canaan.common.exception.ServiceException;
import com.canaan.common.utils.DateUtils;
import com.canaan.common.utils.SecurityUtils;
import com.canaan.common.utils.StringUtils;
import com.canaan.common.utils.TableNoUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 拣货任务单Service业务层处理
 *
 * @author ruoyi
 * @date 2023-02-02
 */
@Service
@Slf4j
public class PickerTaskOrderServiceImpl implements IPickerTaskOrderService {
    @Resource
    private PickerTaskOrderMapper pickerTaskOrderMapper;
    @Resource
    private IWmsPickingRecordService wmsPickingRecordService;
    @Resource
    private IWmsOutStockOrderService wmsOutStockOrderService;
    @Resource
    private IWmsStockOccupyService wmsStockOccupyService;
    @Resource
    private IWmsOutStockDetailOrderService wmsOutStockDetailOrderService;
    @Resource
    private IWmsSalesOrderService wmsSalesOrderService;
    @Resource
    private IPickProductBillService pickProductBillService;
    @Resource
    private IAdjustOutBillService adjustOutBillService;
    @Resource
    private IPurchaseReturnBillService purchaseReturnBillService;
    @Resource
    private IProductQualityMainTaskService productQualityMainTaskService;
    @Resource
    private IProductQualityItemService productQualityItemService;
    @Resource
    private IContainerService containerService;
    @Resource
    private IContainerBarcodeService containerBarcodeService;
    @Resource
    private IWmsStorehouseStockService wmsStorehouseStockService;
    @Resource
    private IProductQualityConfigService productQualityConfigService;
    @Resource
    private IWmsBarcodeRecordService barcodeRecordService;
    @Resource
    private IYardageGoodsTaskOrderService yardageGoodsTaskOrderService;
    @Autowired
    private IYardageGoodsRecordService yardageGoodsRecordService;
    @Autowired
    private IWmsProductService wmsProductService;
    @Autowired
    private IWmsStorehouseLocationService wmsStorehouseLocationService;
    @Autowired
    private IWmsBarcodeRecordService wmsBarcodeRecordService;
    @Autowired
    private IWmsInOutStorageService wmsInOutStorageService;
    @Autowired
    private IMaterialPreparationService materialPreparationService;

    /**
     * 查询拣货任务单
     *
     * @param id 拣货任务单主键
     * @return 拣货任务单
     */
    @Override
    public PickerTaskOrder selectPickerTaskOrderById(Long id) {
        return pickerTaskOrderMapper.selectPickerTaskOrderById(id);
    }

    /**
     * 查询拣货任务单列表
     *
     * @param pickerTaskOrder 拣货任务单
     * @return 拣货任务单
     */
    @Override
    public List<PickerTaskOrder> selectPickerTaskOrderList(PickerTaskOrder pickerTaskOrder) {
        return pickerTaskOrderMapper.selectPickerTaskOrderList(pickerTaskOrder);
    }

    /**
     * 新增拣货任务单
     *
     * @param pickerTaskOrder 拣货任务单
     * @return 结果
     */
    @Override
    public int insertPickerTaskOrder(PickerTaskOrder pickerTaskOrder) {
        if (StringUtils.isEmpty(pickerTaskOrder.getNo())) {
            pickerTaskOrder.setNo(PrefixConstants.PICKING+TableNoUtil.getNo(PickerTaskOrder.class));
        }
        pickerTaskOrder.setCreateBy(SecurityUtils.getUsername());
        pickerTaskOrder.setCreateTime(DateUtils.getNowDate());
        if (!pickerTaskOrder.getStatus().equals(OutOrderStatusEnum.WAITING_PICK.getCode())) {
            pickerTaskOrder.setStatus(OutOrderStatusEnum.NEW.getCode());
        }
        return pickerTaskOrderMapper.insertPickerTaskOrder(pickerTaskOrder);
    }

    /**
     * 批量新增拣货任务单
     *
     * @param pickerTaskOrderList 拣货任务单列表
     * @return 结果
     */
    @Override
    public int batchInsertPickerTaskOrder(List<PickerTaskOrder> pickerTaskOrderList) {
        String username = SecurityUtils.getUsername();
        Date currerTime = DateUtils.getNowDate();
        for (PickerTaskOrder pickerTaskOrder : pickerTaskOrderList) {
            if (StringUtils.isEmpty(pickerTaskOrder.getNo())) {
                pickerTaskOrder.setNo(TableNoUtil.getNo(PickerTaskOrder.class));
            }
            pickerTaskOrder.setCreateBy(username);
            pickerTaskOrder.setCreateTime(currerTime);
            pickerTaskOrder.setStatus(OutOrderStatusEnum.WAITING_PICK.getCode());
        }
        int insertNum = 0;

        for (int i = 0; i < pickerTaskOrderList.size(); ) {
            int endIndex = i + 500;
            if (endIndex > pickerTaskOrderList.size()) {
                endIndex = pickerTaskOrderList.size();
            }
            insertNum = insertNum + pickerTaskOrderMapper.batchInsertPickerTaskOrder(pickerTaskOrderList.subList(i, endIndex));
            i = endIndex;
        }
        return insertNum;

    }

    /**
     * 修改拣货任务单
     *
     * @param pickerTaskOrder 拣货任务单
     * @return 结果
     */
    @Override
    public int updatePickerTaskOrder(PickerTaskOrder pickerTaskOrder) {
        pickerTaskOrder.setUpdateBy(SecurityUtils.getUsername());
        pickerTaskOrder.setUpdateTime(DateUtils.getNowDate());
        return pickerTaskOrderMapper.updatePickerTaskOrder(pickerTaskOrder);
    }

    /**
     * 根据no修改拣货任务单
     *
     * @param pickerTaskOrder 拣货任务单
     * @return 结果
     */
    @Override
    public int updatePickerTaskOrderByNo(PickerTaskOrder pickerTaskOrder) {
        pickerTaskOrder.setUpdateBy(SecurityUtils.getUsername());
        pickerTaskOrder.setUpdateTime(DateUtils.getNowDate());
        return pickerTaskOrderMapper.updatePickerTaskOrderByNo(pickerTaskOrder);
    }

    /**
     * 批量修改拣货任务单
     *
     * @param pickerTaskOrderList 拣货任务单列表
     * @return 结果
     */
    @Override
    public int batchUpdatePickerTaskOrder(List<PickerTaskOrder> pickerTaskOrderList) {
        String username = SecurityUtils.getUsername();
        Date currerTime = DateUtils.getNowDate();
        for (PickerTaskOrder pickerTaskOrder : pickerTaskOrderList) {
            pickerTaskOrder.setUpdateBy(username);
            pickerTaskOrder.setUpdateTime(currerTime);
        }
        int updateNum = 0;
        for (int i = 0; i < pickerTaskOrderList.size(); ) {
            int endIndex = i + 500;
            if (endIndex > pickerTaskOrderList.size()) {
                endIndex = pickerTaskOrderList.size();
            }
            updateNum = updateNum + pickerTaskOrderMapper.batchUpdatePickerTaskOrder(pickerTaskOrderList.subList(i, endIndex));
            i = endIndex;
        }
        return updateNum;
    }

    /**
     * 批量删除拣货任务单
     *
     * @param ids 需要删除的拣货任务单主键集合
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deletePickerTaskOrderByIds(Long[] ids) {
        for (int i = 0; i < ids.length; i++) {
            PickerTaskOrder pickerTaskOrder = this.pickerTaskOrderMapper.selectPickerTaskOrderById(ids[0]);
            if (pickerTaskOrder != null) {
                if (!OutOrderStatusEnum.NEW.getCode().equals(pickerTaskOrder.getStatus())) {
                    throw new ServiceException("拣货单状态为新建才能删除");
                }
                //解除旧占用
                wmsStockOccupyService.stockOccupyCancel(pickerTaskOrder.getNo());
                wmsStockOccupyService.deleteWmsStockOccupyById(pickerTaskOrder.getId());
            }
        }
        return pickerTaskOrderMapper.deletePickerTaskOrderByIds(ids);
    }

    /**
     * 删除拣货任务单信息
     *
     * @param id 拣货任务单主键
     * @return 结果
     */
    @Override
    public int deletePickerTaskOrderById(Long id) {
        return pickerTaskOrderMapper.deletePickerTaskOrderById(id);
    }

    /**
     * 查询拣货任务单
     *
     * @param no 编号
     * @return 拣货任务单
     */
    @Override
    public PickerTaskOrder selectPickerTaskOrderByNo(String no) {
        return pickerTaskOrderMapper.selectPickerTaskOrderByNo(no);
    }

    @Override
    public List<PickerTaskOrder> selectPickerTaskOrderByOutOrderId(Long outOrderId) {
        PickerTaskOrder query = new PickerTaskOrder();
        query.setOutOrderId(outOrderId);
        return pickerTaskOrderMapper.selectPickerTaskOrderList(query);
    }

    /**
     * 批量删除拣货任务单
     *
     * @param nos 需要删除的编号集合
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deletePickerTaskOrderByNos(String[] nos) {
        if (nos == null || nos.length < 1) {
            return 0;
        }
        //查询关联的占用列表并删除
        WmsStockOccupy occupy = new WmsStockOccupy();
        occupy.setType(StockOccupyTypeEnum.OCCUPY.getCode());
        Set<String> delNoSet = new HashSet<>();
        for (int i = 0; i < nos.length; i++) {
            delNoSet.add(nos[i]);
        }
        occupy.setParams(Collections.singletonMap("taskNos", delNoSet));
        List<WmsStockOccupy> occupyList = wmsStockOccupyService.selectWmsStockOccupyList(occupy);
        if (!occupyList.isEmpty()) {
            for (WmsStockOccupy wmsStockOccupy : occupyList) {
                //解除占用
                wmsStockOccupyService.stockOccupyCancel(wmsStockOccupy.getTaskNo());
            }
            String[] occupyNos = occupyList.stream().map(WmsStockOccupy::getNo).toArray(String[]::new);
            wmsStockOccupyService.deleteWmsStockOccupyByNos(occupyNos);
        }

        return pickerTaskOrderMapper.deletePickerTaskOrderByNos(nos);
    }

    /**
     * 删除拣货任务单信息
     *
     * @param no 编号
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deletePickerTaskOrderByNo(String no) {
        if (StringUtils.isNotEmpty(no)) {
            return 0;
        }
        //查询关联的占用列表并删除
        WmsStockOccupy occupy = new WmsStockOccupy();
        occupy.setType(StockOccupyTypeEnum.OCCUPY.getCode());
        occupy.setTaskNo(no);
        List<WmsStockOccupy> occupyList = wmsStockOccupyService.selectWmsStockOccupyList(occupy);
        if (!occupyList.isEmpty()) {
            //解除占用
            wmsStockOccupyService.stockOccupyCancel(no);
            //删除占用
            wmsStockOccupyService.deleteWmsStockOccupyByNo(occupyList.get(0).getNo());
        }
        return pickerTaskOrderMapper.deletePickerTaskOrderByNo(no);
    }

    /**
     * @Description 确认或完成拣货
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int confirmOrComplete(PickerTaskOrderVo params, Boolean isComplete) {
        if (params == null) {
            throw new ServiceException("数据为空");
        }
        PickerTaskOrder taskOrder = this.pickerTaskOrderMapper.selectPickerTaskOrderByNo(params.getNo());
        if (taskOrder == null) {
            throw new ServiceException("找不到拣货任务");
        }
        params.setRecordList(params.getRecordList() == null ? Collections.emptyList() : params.getRecordList());
        if (!isComplete && params.getRecordList().isEmpty()) {
            throw new ServiceException("拣货记录不能为空");
        }
        //已拣货数
        long number = params.getRecordList().stream().mapToLong(WmsPickingRecord::getPickingQty).sum();
        long totalNumber = number + taskOrder.getPickingQty();
        if (taskOrder.getDistributeQty() < totalNumber) {
            throw new ServiceException("拣货数量不能大于分配的数量");
        }
        taskOrder.setStatus(isComplete ? OutOrderStatusEnum.PICKING_FINSH.getCode() : OutOrderStatusEnum.PICKING.getCode());
        Date completeTime = isComplete ? new Date() : null;
        taskOrder.setPickingQty(totalNumber);
        taskOrder.setCompleteTime(completeTime);
        taskOrder.setPickSign(params.getPickSign());
        pickerTaskOrderMapper.updatePickerTaskOrder(taskOrder);
        //获取出入库单明细
        WmsOutStockDetailOrder outStockDetailOrder = wmsOutStockDetailOrderService.selectWmsOutStockDetailOrderById(taskOrder.getOutOrderId());
        //处理拣货记录
        if (!params.getRecordList().isEmpty()) {
            //插入拣货记录
            for (WmsPickingRecord record : params.getRecordList()) {
                record.setOrderDetailNo(taskOrder.getNo());
            }
            List<String> barcodeList = params.getRecordList().stream().map(WmsPickingRecord::getBarcode).collect(Collectors.toList());
            //批量插入拣货记录和处理库存
            wmsPickingRecordService.batchInsertWmsPickingRecord(params.getRecordList());
            //库存占用解锁
            wmsStockOccupyService.stockOccupyUnlock(taskOrder, params.getRecordList(), outStockDetailOrder.getOrderNo());
            //解除条码与容器的绑定并更新容器状态
            this.removeContainerBarcode(barcodeList);
        }
        //修改出库单和明细信息
        if (outStockDetailOrder != null) {
            WmsOutStockOrder outStockOrder = wmsOutStockOrderService.selectWmsOutStockOrderByNo(outStockDetailOrder.getOrderNo());
            if (outStockOrder != null) {
                if (isComplete) {
                    //处理拣货完成的拣货单
                    this.pickComplete(taskOrder);
                } else {
                    //确认拣货
//                    outStockDetailOrder.setPickingQty(outStockDetailOrder.getPickingQty()+taskOrder.getPickingQty());
                    wmsOutStockDetailOrderService.updateWmsOutStockDetailOrder(outStockDetailOrder);
                    outStockOrder.setOrderStatus(OutOrderStatusEnum.PICKING.getCode());
//                    outStockOrder.setTotalActualQty(outStockOrder.getTotalActualQty() + number);
                    wmsOutStockOrderService.updateWmsOutStockOrder(outStockOrder);
                }
            } else {
                throw new ServiceException("出库单不存在");
            }
        }
        return 1;
    }

    @Override
    public int confirmSign(String no) {
        PickerTaskOrder taskOrder = this.pickerTaskOrderMapper.selectPickerTaskOrderByNo(no);
        if (taskOrder == null) {
            throw new ServiceException("找不到拣货任务");
        }
        WmsOutStockDetailOrder detailOrder = this.wmsOutStockDetailOrderService.selectWmsOutStockDetailOrderById(taskOrder.getOutOrderId());
        //判断该出库单明细下的拣货任务是否都完成
        List<PickerTaskOrder> pickerTaskOrderList = this.listPickerTaskOrdeCompleted(detailOrder.getId());
        if (CollectionUtil.isNotEmpty(pickerTaskOrderList)){
            long pcompleNum = pickerTaskOrderList.stream().filter(e->e.getStatus().equals(OutOrderStatusEnum.ACCOMPLISH.getCode())).count();
            if ((pcompleNum+1) == pickerTaskOrderList.size()){
                //拣货任务已完成，再判断是否所有明细都已完成
                WmsOutStockOrder wmsOutStockOrder = this.wmsOutStockOrderService.selectWmsOutStockOrderByNo(detailOrder.getOrderNo());
                if (wmsOutStockOrder!=null){
                    List<WmsOutStockDetailOrder> detailOrderList = this.wmsOutStockDetailOrderService.listByOrderNo(wmsOutStockOrder.getNo());
                    if (CollectionUtil.isNotEmpty(detailOrderList)){
                        long dcompleNum = detailOrderList.stream().filter(e->e.getOrderDetailStatus().equals(OutOrderStatusEnum.ACCOMPLISH.getCode())).count();
                        if ((dcompleNum+1)== detailOrderList.size()){
                            return 1;
                        }
                    }
                }
            }
        }
        return 0;
    }

    //解除绑定条码与托盘的绑定,并判断如果托盘没有绑定条码则将托盘状态更新为空闲
    public void removeContainerBarcode(List<String> barcodeList) {
        Map<String, String> containerMap = new HashMap<>();
        for (String barcode : barcodeList) {
            WmsStorehouseStock stock = this.wmsStorehouseStockService.selectWmsStorehouseStockListByBarcode(barcode);
            if (stock == null) {
                //条码不在库存中需要解绑条码与容器的关系
                List<ContainerBarcode> containerBarcodeList = containerBarcodeService.selectByBarcode(barcode);
                if (CollectionUtil.isNotEmpty(containerBarcodeList)) {
                    ContainerBarcode containerBarcode = containerBarcodeList.get(0);
                    containerMap.put(containerBarcode.getContainerNo(), containerBarcode.getContainerNo());
                    containerBarcodeService.deleteContainerBarcodeById(containerBarcode.getId());
                }
            }
        }
        //查询容器
        if (CollectionUtil.isNotEmpty(containerMap)) {
            for (String containerNo : containerMap.keySet()) {
                List<ContainerBarcode> containerBarcodeList = containerBarcodeService.selectByContainerNo(containerNo);
                if (CollectionUtil.isEmpty(containerBarcodeList)) {
                    Container container = this.containerService.selectContainerByNo(containerNo);
                    if (container != null) {
                        container.setStatus(ContainerStatusEnum.FREE.getCode());
                        containerService.updateContainer(container);
                    } else {
                        log.info("容器不存在");
                    }
                }
            }
        }
    }

    /**
     * 根据出库单明细 查询已完成的拣货单
     *
     * @param outOrderId
     * @return
     */
    public List<PickerTaskOrder> listPickerTaskOrdeCompleted(Long outOrderId) {
        PickerTaskOrder queryPickQuery = new PickerTaskOrder();
        queryPickQuery.setOutOrderId(outOrderId);
        queryPickQuery.setStatus(OutOrderStatusEnum.ACCOMPLISH.getCode());
        List<PickerTaskOrder> pickerTaskOrderList = this.pickerTaskOrderMapper.selectPickerTaskOrderList(queryPickQuery);
        return pickerTaskOrderList;
    }


    /**
     * 处理已完成的拣货单
     *
     * @param order
     */
    @Transactional(rollbackFor = Exception.class)
    public void complete(PickerTaskOrder order) {
        Date completeTime = new Date();
        if (order != null) {
            WmsOutStockDetailOrder outStockDetailOrder = wmsOutStockDetailOrderService.selectWmsOutStockDetailOrderById(order.getOutOrderId());
            if (outStockDetailOrder != null) {
                WmsOutStockOrder outStockOrder = wmsOutStockOrderService.selectWmsOutStockOrderByNo(outStockDetailOrder.getOrderNo());
                ProductQualityMainTask qualityMainTask = this.productQualityMainTaskService.selectProductQualityMainTaskByNo(order.getQualityTaskNo());
                if (qualityMainTask != null) {
                    if (QualityResultEnum.NG.getCode().equals(qualityMainTask.getStatus())) {
                        order.setStatus(OutOrderStatusEnum.NG.getCode());
                        outStockDetailOrder.setOrderDetailStatus(OutOrderStatusEnum.PICKING.getCode());
                        outStockDetailOrder.setPickingQty(outStockDetailOrder.getPickingQty() - order.getPickingQty());
                        this.wmsOutStockDetailOrderService.updateWmsOutStockDetailOrder(outStockDetailOrder);
                        outStockOrder.setOrderStatus(OutOrderStatusEnum.PICKING.getCode());
                        outStockOrder.setTotalActualQty(outStockOrder.getTotalOrderQty() - order.getPickingQty());
                        this.wmsOutStockOrderService.updateWmsOutStockOrder(outStockOrder);
                    } else {
                        order.setStatus(OutOrderStatusEnum.ACCOMPLISH.getCode());
                    }
                } else {
                    order.setStatus(OutOrderStatusEnum.ACCOMPLISH.getCode());
                }
                order.setInStockTime(completeTime);
                this.pickerTaskOrderMapper.updatePickerTaskOrder(order);
                List<PickerTaskOrder> pickerTaskOrderAllList = this.selectPickerTaskOrderByOutOrderId(order.getOutOrderId());
                if (CollectionUtil.isNotEmpty(pickerTaskOrderAllList)) {
                    Long pickCount = pickerTaskOrderAllList.stream().filter(e -> e.getStatus().equals(OutOrderStatusEnum.ACCOMPLISH.getCode()) || e.getStatus().equals(OutOrderStatusEnum.NG.getCode())).count();
                    if (pickCount.intValue() == pickerTaskOrderAllList.size()) {
                        if (outStockDetailOrder != null) {
                            outStockDetailOrder.setOrderDetailStatus(OutOrderStatusEnum.ACCOMPLISH.getCode());
                            this.wmsOutStockDetailOrderService.updateWmsOutStockDetailOrder(outStockDetailOrder);
                            //判断出库单明细是否完成并处理
                            WmsOutStockDetailOrder outStockOrderDetailParams = new WmsOutStockDetailOrder();
                            outStockOrderDetailParams.setOrderNo(outStockDetailOrder.getOrderNo());
                            List<WmsOutStockDetailOrder> detailOrders = wmsOutStockDetailOrderService.selectWmsOutStockDetailOrderList(outStockOrderDetailParams);
                            boolean isAllComplete = detailOrders.stream()
                                    .allMatch(e -> e.getOrderDetailStatus() != null
                                            && OutOrderStatusEnum.ACCOMPLISH.getCode().equals(e.getOrderDetailStatus()));
                            if (isAllComplete) {
                                outStockOrder.setOrderStatus(OutOrderStatusEnum.ACCOMPLISH.getCode());
                                outStockOrder.setCompleteTime(completeTime);
                                this.wmsOutStockOrderService.updateWmsOutStockOrder(outStockOrder);
                                Integer status = OutOrderStatusEnum.ACCOMPLISH.getCode();
                                if (StringUtils.isNotEmpty(outStockOrder.getRelOrderNo())
                                        && OutStockOrderTypeEnum.SALES.getCode().equals(outStockOrder.getOrderType())) {
                                    //销售单的状态需改为已发货待确认
                                    WmsSalesOrder salesOrder = wmsSalesOrderService.selectWmsSalesOrderByNo(outStockOrder.getRelOrderNo());
                                    salesOrder.setOrderStatus(SaleOrderEnum.DELIVERY_WAIT_CONFIRMATIO.getCode());
                                    salesOrder.setCompleteTime(completeTime);
                                    wmsSalesOrderService.updateWmsSalesOrder(salesOrder);
                                } else if (StringUtils.isNotEmpty(outStockOrder.getRelOrderNo())
                                        && OutStockOrderTypeEnum.PICK.getCode().equals(outStockOrder.getOrderType())) {
                                    //领料单
                                    PickProductBill bill = pickProductBillService.selectPickProductBillByNo(outStockOrder.getRelOrderNo());
                                    if (!status.equals(bill.getStatus())) {
                                        bill.setPickSign(order.getPickSign());
                                        bill.setStatus(status);
                                        bill.setCompleteTime(completeTime);
                                        pickProductBillService.updatePickProductBill(bill);
                                    }
                                } else if (StringUtils.isNotEmpty(outStockOrder.getRelOrderNo())
                                        && OutStockOrderTypeEnum.ADJUST.getCode().equals(outStockOrder.getOrderType())) {
                                    //调拨出库单
                                    AdjustOutBill bill = adjustOutBillService.selectAdjustOutBillByNo(outStockOrder.getRelOrderNo());
                                    if (!status.equals(bill.getStatus())) {
                                        bill.setStatus(status);
                                        bill.setCompleteTime(completeTime);
                                        adjustOutBillService.updateAdjustOutBill(bill);
                                    }
                                } else if (StringUtils.isNotEmpty(outStockOrder.getRelOrderNo())
                                        && OutStockOrderTypeEnum.RETURN.getCode().equals(outStockOrder.getOrderType())) {
                                    //退货出库单
                                    PurchaseReturnBill bill = purchaseReturnBillService.selectPurchaseReturnBillByNo(outStockOrder.getRelOrderNo());
                                    if (!status.equals(bill.getStatus())) {
                                        bill.setStatus(status);
                                        bill.setCompleteTime(completeTime);
                                        purchaseReturnBillService.updatePurchaseReturnBill(bill);
                                    }
                                } else if (StringUtils.isNotEmpty(outStockOrder.getRelOrderNo())
                                        && OutStockOrderTypeEnum.MP.getCode().equals(outStockOrder.getOrderType())) {
                                    //生产备料申请
                                    MaterialPreparation preparation = materialPreparationService.selectMaterialPreparationByNo(outStockOrder.getRelOrderNo());
                                    //判断拣货单的数量是否都已满足需备料的数量，如果满足将备料申请状态更新为完成
                                    List<WmsOutStockOrder> outStockOrderList = wmsOutStockOrderService.selectListOrderByRelOrderNo(preparation.getNo(), OutStockOrderTypeEnum.MP.getCode());
                                    if (CollectionUtil.isNotEmpty(outStockOrderList)){
                                        //筛选已完成的
                                        List<WmsOutStockOrder> outStockOrderList1 = outStockOrderList.stream().filter(e->e.getOrderStatus().equals(OutOrderStatusEnum.ACCOMPLISH.getCode())).collect(Collectors.toList());
                                        Long num = outStockOrderList1.stream().collect(Collectors.summingLong(WmsOutStockOrder::getDistributeQty));
                                        if (preparation.getWorkOrderQty().longValue()==num){
                                            preparation.setOrderStatus(OutOrderStatusEnum.ACCOMPLISH.getCode());
                                            preparation.setCompleteTime(new Date());
                                            materialPreparationService.updateMaterialPreparation(preparation);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

        }
    }

    /**
     * 备料完成码货
     * @param confirmVo
     * @param isComplete
     * @return
     */
    @Override
    public int confirmOrCompleteYard(YardageGoodsTaskOrderConfirmVo confirmVo, Boolean isComplete) {
        if (confirmVo == null) {
            throw new ServiceException("数据为空");
        }
        PickerTaskOrder taskOrder = this.pickerTaskOrderMapper.selectPickerTaskOrderByNo(confirmVo.getNo());
        if (taskOrder == null) {
            throw new ServiceException("找不到码货任务");
        }
        WmsOutStockDetailOrder outStockDetailOrder = this.wmsOutStockDetailOrderService.selectWmsOutStockDetailOrderById(taskOrder.getOutOrderId());
        if (outStockDetailOrder == null){
            throw new ServiceException("备料拣货单据不存在");
        }
        List<YardageGoodsRecord> recordList = confirmVo.getYardageGoodsRecordList() == null ?
                Collections.emptyList() : confirmVo.getYardageGoodsRecordList();
        if (!isComplete && recordList.isEmpty()) {
            throw new ServiceException("码货记录不能为空");
        }
        //提取容器编号更新容器状态
        List<String> containerList = recordList.stream().map(YardageGoodsRecord::getContainerNo).distinct().collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(containerList)){
            containerList.stream().forEach(e->{
                this.yardageGoodsTaskOrderService.updateContainerStatus(e);
            });
        }
        long number = recordList.stream().mapToLong(YardageGoodsRecord::getPickingQty).sum();
         long yardQt = 0;
        if( taskOrder.getYardQty()!=null){
            yardQt = taskOrder.getYardQty();
        }
        long totalNumber = number + yardQt;
        if (!recordList.isEmpty()) {
            //已码货
            if (taskOrder.getOrderQty() < number) {
                throw new ServiceException("入库数量不能大于单据数量");
            }
            //插入码货记录
            for (YardageGoodsRecord yardageGoodsRecord : recordList) {
                yardageGoodsRecord.setTaskNo(taskOrder.getNo());
                yardageGoodsRecord.setWhetherMp(WhetherEnum.Y.getCode());
                if(StringUtils.isEmpty(yardageGoodsRecord.getProductNo())) {
                    yardageGoodsRecord.setProductNo(taskOrder.getProductNo());
                }
            }
            yardageGoodsRecordService.batchInsertYardageGoodsRecord(recordList);
            WmsStorehouseLocation location = new WmsStorehouseLocation();
            location.setStorehouseNo(taskOrder.getStorehouseNo());
            location.setStorehouseAreaNo(taskOrder.getStorehouseAreaNo());
            List<WmsStorehouseLocation> locationList = wmsStorehouseLocationService.selectWmsStorehouseLocationList(location);
            Map<String, WmsStorehouseLocation>   locationMap = locationList.stream()
                    .collect(Collectors.toMap(WmsStorehouseLocation::getNo, e -> e));
            //判断库位是否正确
            Set<String> errorLocationNos = recordList.stream().map(YardageGoodsRecord::getStorehouseLocationNo)
                    .filter(e -> !locationMap.containsKey(e)).collect(Collectors.toSet());
            if (!errorLocationNos.isEmpty()) {
                throw new ServiceException(errorLocationNos + "该备料区不存在此库位");
            }
            //获取和校验物料信息
            WmsProduct product = wmsProductService.selectWmsProductByProductNo(taskOrder.getProductNo());
            if (product == null) {
                throw new ServiceException("物料不存在");
            }
            MaterialPreparation preparation = this.materialPreparationService.selectMaterialPreparationByNo(taskOrder.getRelOrderNo());
            if (preparation==null){
                throw new ServiceException("生产备料申请单不存在");
            }
            //处理库存信息
            this.buildStock(taskOrder,recordList,locationMap,product,outStockDetailOrder.getOrderNo(),preparation.getWorkOrderNo());
        }
        //更新拣货任务状态为码货中
        Date completeTime = isComplete ? new Date() : null;
        taskOrder.setStatus(OutOrderStatusEnum.YARD.getCode());
        taskOrder.setCompleteTime(completeTime);
        taskOrder.setYardQty(totalNumber);
        this.updatePickerTaskOrder(taskOrder);
        //完成处理
        if (isComplete) {
            this.complete(taskOrder);
        }

        return 1;
    }

    /**
     * 处理库存信息
     */
    void buildStock(PickerTaskOrder taskOrder, List<YardageGoodsRecord> recordList, Map<String, WmsStorehouseLocation> locationMap, WmsProduct product, String bussinessNo,String workNo){
        for (YardageGoodsRecord record : recordList) {
            //获取库区编号
            String storehouseAreaNo = locationMap.containsKey(record.getStorehouseLocationNo()) ?
                    locationMap.get(record.getStorehouseLocationNo()).getStorehouseAreaNo() : "";
            //获取条码
            WmsBarcodeRecord barcodeRecord = wmsBarcodeRecordService.getByBarcode(record.getBarCode());
            //入库记录初始化
            WmsInOutStorage inStorage = new WmsInOutStorage();
            inStorage.setProductNo(taskOrder.getProductNo());
            inStorage.setProductName(product.getProductName());
            inStorage.setProductUnit(product.getCompany());
            inStorage.setStorehouseNo(taskOrder.getStorehouseNo());
            inStorage.setAreaNo(storehouseAreaNo);
            inStorage.setStorehouseLocationNo(record.getStorehouseLocationNo());
            inStorage.setBatchNo(barcodeRecord.getBatchNo());
            inStorage.setBarcode(record.getBarCode());
            inStorage.setQuantity(record.getPickingQty());
            inStorage.setRelNo(taskOrder.getRelOrderNo());
            inStorage.setBusinessNo(bussinessNo);
            inStorage.setType(InOutStockTypeEnum.MP_IN.getCode().longValue());
            inStorage.setOperation(InOutStorageOperationEnum.IN.getCode());
            inStorage.setWorkNo(workNo);
            wmsInOutStorageService.insertWmsInOutStorage(inStorage);
            //将条码状态更新为已入库
            barcodeRecord.setStatus(BarcodeRecordStatusEnum.IN.getCode());
            wmsBarcodeRecordService.updateWmsBarcodeRecord(barcodeRecord);
        }
    }
    /**
     * 处理拣货完成的拣货单
     *
     * @param order
     */
    @Transactional(rollbackFor = Exception.class)
    public void pickComplete(PickerTaskOrder order) {
        Date completeTime = new Date();
        if (order != null) {
            order.setStatus(OutOrderStatusEnum.PICKING_FINSH.getCode());
            order.setCompleteTime(completeTime);
            this.pickerTaskOrderMapper.updatePickerTaskOrder(order);
            WmsOutStockDetailOrder outStockDetailOrder = this.wmsOutStockDetailOrderService.selectWmsOutStockDetailOrderById(order.getOutOrderId());
            WmsOutStockOrder outStockOrder = null;
            if (outStockDetailOrder != null) {
                outStockDetailOrder.setPickingQty(outStockDetailOrder.getPickingQty() + order.getPickingQty());
                wmsOutStockDetailOrderService.updateWmsOutStockDetailOrder(outStockDetailOrder);
                outStockOrder = this.wmsOutStockOrderService.selectWmsOutStockOrderByNo(outStockDetailOrder.getOrderNo());
                if (outStockOrder != null) {
                    outStockOrder.setOrderStatus(OutOrderStatusEnum.PICKING.getCode());
                    outStockOrder.setTotalActualQty(outStockOrder.getTotalActualQty() + order.getPickingQty());
                    wmsOutStockOrderService.updateWmsOutStockOrder(outStockOrder);
                }
            }
            //如果不是备料拣货，需要判断是否所有拣货单都完成
            if ( OutStockOrderTypeEnum.MP.getCode()!= outStockOrder.getOrderType()){
                List<PickerTaskOrder> pickerTaskOrderAllList = this.selectPickerTaskOrderByOutOrderId(order.getOutOrderId());
                if (CollectionUtil.isNotEmpty(pickerTaskOrderAllList)) {
                    //判断是不是所有拣货都拣货完成
                    Long pickCount = pickerTaskOrderAllList.stream().filter(e -> e.getStatus().equals(OutOrderStatusEnum.PICKING_FINSH.getCode()) || e.getStatus().equals(OutOrderStatusEnum.ACCOMPLISH.getCode()) || e.getStatus().equals(OutOrderStatusEnum.NG.getCode())).count();
                    if (pickCount.intValue() == pickerTaskOrderAllList.size()) {
                        if (outStockOrder.getOrderType().equals(OutStockOrderTypeEnum.SALES.getCode())) {
                            for (PickerTaskOrder taskOrder : pickerTaskOrderAllList) {
                                if (taskOrder.getStatus().equals(OutOrderStatusEnum.PICKING_FINSH.getCode())) {
                                    if (this.productQualityItemService.isOqc(taskOrder.getProductNo())) {
                                        if (StringUtils.isEmpty(taskOrder.getQualityTaskNo())) {
                                            this.executeOqc(taskOrder);
                                        }
                                    } else {
                                        //已完成
                                        this.complete(taskOrder);
                                    }
                                }
                            }
                        } else {
                            for (PickerTaskOrder taskOrder : pickerTaskOrderAllList) {
                                if (taskOrder.getStatus().equals(OutOrderStatusEnum.PICKING_FINSH.getCode())) {
                                    //已完成
                                    this.complete(taskOrder);
                                }
                            }
                        }

                    }
                }
            }
        }
    }

    /**
     * 处理出货检
     *
     * @param order
     */
    public void executeOqc(PickerTaskOrder order) {
        if (order != null) {
            //查询拣货记录
            WmsPickingRecord recordQ = new WmsPickingRecord();
            recordQ.setOrderDetailNo(order.getNo());
            List<WmsPickingRecord> recordList = this.wmsPickingRecordService.selectWmsPickingRecordList(recordQ);
            //库存的有效天数如果大于物料的超期天数则判断是否需要出货检，否则只判断是否需要出货检
            ProductQualityConfig config = productQualityConfigService.getByProductNo(order.getProductNo());
            if (config != null) {
                if (config.getOverduePeriod() > 0) {
                    boolean isOqc = this.isOverduePeriod(recordList, order, config.getOverduePeriod());
                    if (isOqc) {
                        if (StringUtils.isEmpty(order.getQualityTaskNo())) {
                            if (this.productQualityItemService.isOqc(order.getProductNo())) {
                                createOQC(order);
                            }
                        }
                    }
                } else {
                    if (StringUtils.isEmpty(order.getQualityTaskNo())) {
                        if (this.productQualityItemService.isOqc(order.getProductNo())) {
                            createOQC(order);
                        }
                    }
                }
            } else {
                if (StringUtils.isEmpty(order.getQualityTaskNo())) {
                    if (this.productQualityItemService.isOqc(order.getProductNo())) {
                        createOQC(order);
                    }
                }
            }
        }
    }

    /**
     * 生成出货检
     *
     * @param order
     */
    public void createOQC(PickerTaskOrder order) {
        //生成出货检任务
        ProductQualityMainTask task = new ProductQualityMainTask();
        task.setProductNo(order.getProductNo());
        task.setProductName(order.getProductName());
        task.setStatus(QualityTaskStatusEnum.WAIT.getCode());
        task.setQualityType(QualityTypeEnum.OQC.getCode());
        task.setTotalQuantity(BigDecimal.valueOf(order.getDistributeQty()));
        task.setPickerTaskNo(order.getNo());
        task.setStorehouseNo(order.getStorehouseNo());
        //明细
        WmsOutStockDetailOrder outStockDetailOrder = this.wmsOutStockDetailOrderService.selectWmsOutStockDetailOrderById(order.getOutOrderId());
        if (outStockDetailOrder != null) {
            task.setBusinessNo(outStockDetailOrder.getOrderNo());
            WmsOutStockOrder outStockOrder = this.wmsOutStockOrderService.selectWmsOutStockOrderByNo(outStockDetailOrder.getOrderNo());
            if (outStockOrder != null) {
                task.setSourceNo(outStockOrder.getRelOrderNo());
            }
        }
        this.productQualityMainTaskService.insertProductQualityMainTask(task);
        order.setQualityTaskNo(task.getNo());
        order.setStatus(OutOrderStatusEnum.TO_BE_INSPECTED.getCode());
        this.pickerTaskOrderMapper.updatePickerTaskOrder(order);
    }

    /**
     * 库存是否超期
     *
     * @param recordList
     * @param order
     * @return
     */
    public boolean isOverduePeriod(List<WmsPickingRecord> recordList, PickerTaskOrder order, Integer overduePeriod) {
        boolean isOqc = false;
        if (CollectionUtil.isNotEmpty(recordList)) {
            Date effectiveDate = null;
            for (WmsPickingRecord pickingRecord : recordList) {
                WmsStorehouseStock stock = wmsStorehouseStockService.selectWmsStorehouseStockListByBarcode(pickingRecord.getBarcode());
                if (stock == null) {
                    //如果库存不存在,获取条码信息
                    WmsBarcodeRecord barcodeRecord = this.barcodeRecordService.getByBarcode(pickingRecord.getBarcode());
                    if (barcodeRecord != null) {
                        effectiveDate = barcodeRecord.getEffectiveDate();
                    }
                } else {
                    effectiveDate = stock.getEffectiveDate();
                }
                if (effectiveDate != null) {
                    Long diff = DateUtil.betweenDay(effectiveDate, DateUtil.date(), false);
                    //如果大于物料设置的超期天数则需要出货检
                    if (diff.intValue() > overduePeriod) {
                        isOqc = true;
                        break;
                    }

                }
            }
        }
        return isOqc;
    }

}
